#ifndef FACTORY_H
#define FACTORY_H

#include <iostream>
#include <string>
#include <map>

template<class Base>
struct FactoryObjectBase
{
    virtual Base* create() = 0;
};


template<class Base, class Drived>
struct FactoryObject : public FactoryObjectBase<Base>
{
    virtual Base* create() override
    {
        return new Drived;
    }
};


template<class Base>
struct Factory
{
    static Factory& Instance()
    {
        static Factory instance;
        return instance;
    }

    void regist(std::string name, FactoryObjectBase<Base>* ptr)
    {
        machine.insert({name, ptr});
    }

    Base* create(std::string name)
    {
        if(machine.find(name) != machine.end())
        {
            return machine[name]->create();
        }
        
        return nullptr;
    }

    std::map<std::string, FactoryObjectBase<Base>*> machine;
};


template<class Base, class Drived>
struct FactoryRegister
{
    FactoryRegister(std::string name)
    {
        Factory<Base>::Instance().regist(name, new FactoryObject<Base, Drived>{});
    }
};


#endif